package com.the4man.cnbdw.service;

import com.the4man.cnbdw.exception.BusinessException;
import com.the4man.cnbdw.utils.Page;
import com.the4man.framework.base.BaseService;
import com.the4man.framework.utils.ReflectUtil;
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;

import java.io.Serializable;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

/**
 * Created by lenovo on 2017/12/12.
 */
public abstract class AbstractService<T> extends BaseService<T> implements ApplicationContextAware {
    private ApplicationContext appContext;

    public AbstractService() {
    }

    public int insert(Object record) throws SecurityException, NoSuchMethodException, IllegalArgumentException, IllegalAccessException, InvocationTargetException, ClassNotFoundException {
        String cname = record.getClass().getSimpleName();
        String mapperString = cname.substring(0, 1).toLowerCase() + cname.substring(1) + "Mapper";
        Object mapper = this.appContext.getBean(mapperString);
        Method method = this.getMethodContainsSuperClass(mapper.getClass(), "insert", new Class[]{this.getTruthClass(record)});
        Object result = method.invoke(mapper, new Object[]{record});
        return result != null?Integer.parseInt(result.toString()):0;
    }

    public int insertTwo(Object record) throws SecurityException, NoSuchMethodException, IllegalArgumentException, IllegalAccessException, InvocationTargetException, ClassNotFoundException {
        String cname = record.getClass().getSimpleName();
        String mapperString = cname.substring(0, 1).toLowerCase() + cname.substring(1) + "Mapper";
        Object mapper = this.appContext.getBean(mapperString);
        Method method = this.getMethodContainsSuperClass(mapper.getClass(), "insertTwo", new Class[]{this.getTruthClass(record)});
        Object result = method.invoke(mapper, new Object[]{record});
        return result != null?Integer.parseInt(result.toString()):0;
    }

    public int insertSelective(Object record) throws SecurityException, NoSuchMethodException, IllegalArgumentException, IllegalAccessException, InvocationTargetException, ClassNotFoundException {
        String pojoName = this.getTruthClass(record).getSimpleName();
        Object mapper = this.getMapper(pojoName);
        Method method = mapper.getClass().getMethod("insertSelective", new Class[]{this.getTruthClass(record)});
        Object result = method.invoke(mapper, new Object[]{record});
        return result != null?Integer.parseInt(result.toString()):0;
    }

    public int deleteByPrimaryKey(Serializable id, Class recordClass) throws SecurityException, NoSuchMethodException, IllegalArgumentException, IllegalAccessException, InvocationTargetException {
        String cname = recordClass.getSimpleName();
        Object mapper = this.getMapper(cname);
        Method method = mapper.getClass().getMethod("deleteByPrimaryKey", new Class[]{id.getClass()});
        Object result = method.invoke(mapper, new Object[]{id});
        return result != null?Integer.parseInt(result.toString()):0;
    }

    public int countByExample(Object example) throws SecurityException, NoSuchMethodException, IllegalArgumentException, IllegalAccessException, InvocationTargetException {
        String pojoName = example.getClass().getSimpleName().replaceAll("Example$", "");
        Object mapper = this.getMapper(pojoName);
        Method method = mapper.getClass().getMethod("countByExample", new Class[]{example.getClass()});
        Object result = method.invoke(mapper, new Object[]{example});
        System.out.println("result=" + result);
        return result != null?Integer.parseInt(result.toString()):0;
    }

    public int deleteByExample(Object example) throws SecurityException, NoSuchMethodException, IllegalArgumentException, IllegalAccessException, InvocationTargetException {
        String pojoName = example.getClass().getSimpleName().replaceAll("Example$", "");
        Object mapper = this.getMapper(pojoName);
        Method method = mapper.getClass().getMethod("deleteByExample", new Class[]{example.getClass()});
        Object result = method.invoke(mapper, new Object[]{example});
        return result != null?Integer.parseInt(result.toString()):0;
    }

    public List selectByExample(Object example) throws SecurityException, NoSuchMethodException, IllegalArgumentException, IllegalAccessException, InvocationTargetException {
        String pojoName = example.getClass().getSimpleName().replaceAll("Example$", "");
        Object mapper = this.getMapper(pojoName);
        Method method = this.getMethodContainsSuperClass(mapper.getClass(), "selectByExample", new Class[]{example.getClass()});
        Object result = method.invoke(mapper, new Object[]{example});
        return result != null?(List)result:null;
    }

    public List selectExByExample(Object example) throws SecurityException, NoSuchMethodException, IllegalArgumentException, IllegalAccessException, InvocationTargetException {
        String pojoName = example.getClass().getSimpleName().replaceAll("Example$", "");
        Object mapper = this.getMapper(pojoName);
        Method method = this.getMethodContainsSuperClass(mapper.getClass(), "selectExByExample", new Class[]{example.getClass()});
        Object result = method.invoke(mapper, new Object[]{example});
        return result != null?(List)result:null;
    }

    public List selectByExampleWithFetchProperty(Object example, String[] propertyNames) throws BusinessException, Exception {
        List rtn = this.selectByExample(example);
        this.fetchPropertyOfList(rtn, propertyNames);
        return rtn;
    }

    public void selectByExample(Object example, Page page) throws SecurityException, NoSuchMethodException, IllegalArgumentException, IllegalAccessException, InvocationTargetException {
        String pojoName = example.getClass().getSimpleName().replaceAll("Example$", "");
        System.out.println("+++++++++" + example.toString());
        System.out.println("+++++++++" + pojoName);
        Object mapper = this.getMapper(pojoName);
        int limitStart = (page.getCurPage() - 1) * page.getRowsPerPage();
        if(page.getCurPage() > 0 && page.getRowsPerPage() > 0) {
            List<Class> ptypes = new ArrayList();
            ptypes.add(Integer.TYPE);
            ReflectUtil.invoke(example, "setLimitStart", ptypes, new Object[]{Integer.valueOf(limitStart)});
            ReflectUtil.invoke(example, "setRowsPerPage", ptypes, new Object[]{Integer.valueOf(page.getRowsPerPage())});
        }

        Method method = mapper.getClass().getMethod("selectByExample", new Class[]{example.getClass()});
        Object result = method.invoke(mapper, new Object[]{example});
        if(result != null) {
            page.setData((List)result);
        }

        method = mapper.getClass().getMethod("countByExample", new Class[]{example.getClass()});
        result = method.invoke(mapper, new Object[]{example});
        if(result != null) {
            page.setRowCount(Integer.parseInt(result.toString()));
        }

    }

    public void selectPrintByExample(Object example, Page page) throws SecurityException, NoSuchMethodException, IllegalArgumentException, IllegalAccessException, InvocationTargetException {
        String pojoName = example.getClass().getSimpleName().replaceAll("Example$", "");
        System.out.println("+++++++++" + example.toString());
        System.out.println("+++++++++" + pojoName);
        Object mapper = this.getMapper(pojoName);
        int limitStart = (page.getCurPage() - 1) * page.getRowsPerPage();
        if(page.getCurPage() > 0 && page.getRowsPerPage() > 0) {
            List<Class> ptypes = new ArrayList();
            ptypes.add(Integer.TYPE);
            ReflectUtil.invoke(example, "setLimitStart", ptypes, new Object[]{Integer.valueOf(limitStart)});
            ReflectUtil.invoke(example, "setRowsPerPage", ptypes, new Object[]{Integer.valueOf(page.getRowsPerPage())});
        }

        Method method = mapper.getClass().getMethod("selectPrintByExample", new Class[]{example.getClass()});
        Object result = method.invoke(mapper, new Object[]{example});
        if(result != null) {
            page.setData((List)result);
        }

        method = mapper.getClass().getMethod("countByExample", new Class[]{example.getClass()});
        result = method.invoke(mapper, new Object[]{example});
        if(result != null) {
            page.setRowCount(Integer.parseInt(result.toString()));
        }

    }

    public void selectByExampleWithFetchProperty(Object example, Page page, String[] propertyNames) throws BusinessException, Exception {
        this.selectByExample(example, page);
        this.fetchPropertyOfList(page.getData(), propertyNames);
    }

    public Object selectByPrimaryKey(Serializable id, Class recordClass) throws SecurityException, NoSuchMethodException, IllegalArgumentException, IllegalAccessException, InvocationTargetException {
        String pojoName = recordClass.getSimpleName();
        Object mapper = this.getMapper(pojoName);
        Method method = mapper.getClass().getMethod("selectByPrimaryKey", new Class[]{id.getClass()});
        Object result = method.invoke(mapper, new Object[]{id});
        return result != null?result:null;
    }

    public Object selectByPrimaryKeyWithFetchProperty(Serializable id, Class recordClass, String[] propertyNames) throws BusinessException, Exception {
        Object obj = this.selectByPrimaryKey(id, recordClass);
        this.fetchPropertys(obj, propertyNames);
        return obj;
    }

    public int updateByExampleSelective(Object record, Object example) throws SecurityException, NoSuchMethodException, IllegalArgumentException, IllegalAccessException, InvocationTargetException, ClassNotFoundException {
        String pojoName = this.getTruthClass(record).getSimpleName();
        System.out.println("pojoName :  " + pojoName);
        Object mapper = this.getMapper(pojoName);
        System.out.println("mapper :  " + mapper);
        Method method = mapper.getClass().getMethod("updateByExampleSelective", new Class[]{record.getClass(), example.getClass()});
        Object result = method.invoke(mapper, new Object[]{record, example});
        return result != null?Integer.parseInt(result.toString()):0;
    }

    public int updateByExample(Object record, Object example) throws SecurityException, NoSuchMethodException, IllegalArgumentException, IllegalAccessException, InvocationTargetException, ClassNotFoundException {
        String pojoName = this.getTruthClass(record).getSimpleName();
        Object mapper = this.getMapper(pojoName);
        Method method = mapper.getClass().getMethod("updateByExample", new Class[]{this.getTruthClass(record), example.getClass()});
        Object result = method.invoke(mapper, new Object[]{record, example});
        return result != null?Integer.parseInt(result.toString()):0;
    }

    public int updateByPrimaryKeySelective(Object record) throws SecurityException, NoSuchMethodException, IllegalArgumentException, IllegalAccessException, InvocationTargetException, ClassNotFoundException {
        String pojoName = this.getTruthClass(record).getSimpleName();
        System.out.println("pojoName :  " + pojoName);
        Object mapper = this.getMapper(pojoName);
        System.out.println("mapper :  " + mapper);
        Method method = mapper.getClass().getMethod("updateByPrimaryKeySelective", new Class[]{this.getTruthClass(record)});
        Object result = method.invoke(mapper, new Object[]{record});
        return result != null?Integer.parseInt(result.toString()):0;
    }

    public int updateByPrimaryKey(Object record) throws SecurityException, NoSuchMethodException, IllegalArgumentException, IllegalAccessException, InvocationTargetException, ClassNotFoundException {
        String pojoName = this.getTruthClass(record).getSimpleName();
        Object mapper = this.getMapper(pojoName);
        Method method = mapper.getClass().getMethod("updateByPrimaryKey", new Class[]{this.getTruthClass(record)});
        Object result = method.invoke(mapper, new Object[]{record});
        return result != null?Integer.parseInt(result.toString()):0;
    }

    protected Object getMapper(String pojoName) {
        pojoName = pojoName.indexOf("$") >= 0?pojoName.substring(0, pojoName.indexOf("$")):pojoName;
        String mapperString = pojoName.substring(0, 1).toLowerCase() + pojoName.substring(1) + "Mapper";
        Object mapper = this.appContext.getBean(mapperString);
        return mapper;
    }

    protected Class getTruthClass(Object obj) throws ClassNotFoundException {
        String cname = obj.getClass().getName();
        cname = cname.indexOf("$") >= 0?cname.substring(0, cname.indexOf("$")):cname;
        return Class.forName(cname);
    }

    public void setApplicationContext(ApplicationContext ctx) throws BeansException {
        this.appContext = ctx;
    }

    private void fetchProperty(Object obj, String propertyName) throws SecurityException, IllegalArgumentException, NoSuchMethodException, IllegalAccessException, InvocationTargetException {
        if(obj != null) {
            ReflectUtil.getProperty(obj, propertyName);
        }
    }

    private void fetchPropertys(Object obj, String[] propertyNames) throws SecurityException, IllegalArgumentException, NoSuchMethodException, IllegalAccessException, InvocationTargetException {
        String[] var6 = propertyNames;
        int var5 = propertyNames.length;

        for(int var4 = 0; var4 < var5; ++var4) {
            String propertyName = var6[var4];
            this.fetchProperty(obj, propertyName);
        }

    }

    private void fetchPropertyOfList(List list, String[] propertyNames) throws SecurityException, IllegalArgumentException, NoSuchMethodException, IllegalAccessException, InvocationTargetException {
        String[] var6 = propertyNames;
        int var5 = propertyNames.length;

        for(int var4 = 0; var4 < var5; ++var4) {
            String propertyName = var6[var4];
            Iterator var8 = list.iterator();

            while(var8.hasNext()) {
                Object obj = var8.next();
                ReflectUtil.getProperty(obj, propertyName);
            }
        }

    }

    private Method getMethodContainsSuperClass(Class targetClazz, String methodName, Class... parameterClazzes) throws SecurityException, NoSuchMethodException {
        Method method = null;
        method = targetClazz.getMethod(methodName, parameterClazzes);
        if(method == null) {
            Class[] interfaces = targetClazz.getInterfaces();
            Class[] var9 = interfaces;
            int var8 = interfaces.length;

            for(int var7 = 0; var7 < var8; ++var7) {
                Class c = var9[var7];
                method = this.getMethodContainsSuperClass(c, methodName, parameterClazzes);
                if(method != null) {
                    break;
                }
            }

            if(method == null && targetClazz.getSuperclass() != null) {
                method = this.getMethodContainsSuperClass(targetClazz.getSuperclass(), methodName, parameterClazzes);
            }
        }

        return method;
    }

    private Field getFieldContainsSuperClass(Class targetClazz, String fieldName) throws SecurityException, NoSuchFieldException {
        Field field = null;
        field = targetClazz.getDeclaredField(fieldName);
        if(field == null) {
            Class[] interfaces = targetClazz.getInterfaces();
            Class[] var8 = interfaces;
            int var7 = interfaces.length;

            for(int var6 = 0; var6 < var7; ++var6) {
                Class c = var8[var6];
                field = this.getFieldContainsSuperClass(c, fieldName);
                if(field != null) {
                    break;
                }
            }

            if(field == null && targetClazz.getSuperclass() != null) {
                field = this.getFieldContainsSuperClass(targetClazz.getSuperclass(), fieldName);
            }
        }

        return field;
    }

    public void selectFullByExample(Object example, Page page) throws SecurityException, NoSuchMethodException, IllegalArgumentException, IllegalAccessException, InvocationTargetException {
        String pojoName = example.getClass().getSimpleName().replaceAll("Example$", "");
        Object mapper = this.getMapper(pojoName);
        int limitStart = (page.getCurPage() - 1) * page.getRowsPerPage();
        if(page.getCurPage() > 0 && page.getRowsPerPage() > 0) {
            List<Class> ptypes = new ArrayList();
            ptypes.add(Integer.TYPE);
            ReflectUtil.invoke(example, "setLimitStart", ptypes, new Object[]{Integer.valueOf(limitStart)});
            ReflectUtil.invoke(example, "setRowsPerPage", ptypes, new Object[]{Integer.valueOf(page.getRowsPerPage())});
        }

        Method method = mapper.getClass().getMethod("selectFullByExample", new Class[]{example.getClass()});
        Object result = method.invoke(mapper, new Object[]{example});
        if(result != null) {
            page.setData((List)result);
        }

        method = mapper.getClass().getMethod("countByExample", new Class[]{example.getClass()});
        result = method.invoke(mapper, new Object[]{example});
        if(result != null) {
            page.setRowCount(Integer.parseInt(result.toString()));
        }

    }

    public void selectRoomByExample(Object example, Page page) throws SecurityException, NoSuchMethodException, IllegalArgumentException, IllegalAccessException, InvocationTargetException {
        String pojoName = example.getClass().getSimpleName().replaceAll("Example$", "");
        Object mapper = this.getMapper(pojoName);
        int limitStart = (page.getCurPage() - 1) * page.getRowsPerPage();
        if(page.getCurPage() > 0 && page.getRowsPerPage() > 0) {
            List<Class> ptypes = new ArrayList();
            ptypes.add(Integer.TYPE);
            ReflectUtil.invoke(example, "setLimitStart", ptypes, new Object[]{Integer.valueOf(limitStart)});
            ReflectUtil.invoke(example, "setRowsPerPage", ptypes, new Object[]{Integer.valueOf(page.getRowsPerPage())});
        }

        Method method = mapper.getClass().getMethod("selectRoomByExample", new Class[]{example.getClass()});
        Object result = method.invoke(mapper, new Object[]{example});
        if(result != null) {
            page.setData((List)result);
        }

        method = mapper.getClass().getMethod("countByExample", new Class[]{example.getClass()});
        result = method.invoke(mapper, new Object[]{example});
        if(result != null) {
            page.setRowCount(Integer.parseInt(result.toString()));
        }

    }

    public void selectOneByExample(Object example, Page page) throws SecurityException, NoSuchMethodException, IllegalArgumentException, IllegalAccessException, InvocationTargetException {
        String pojoName = example.getClass().getSimpleName().replaceAll("Example$", "");
        Object mapper = this.getMapper(pojoName);
        int limitStart = (page.getCurPage() - 1) * page.getRowsPerPage();
        if(page.getCurPage() > 0 && page.getRowsPerPage() > 0) {
            List<Class> ptypes = new ArrayList();
            ptypes.add(Integer.TYPE);
            ReflectUtil.invoke(example, "setLimitStart", ptypes, new Object[]{Integer.valueOf(limitStart)});
            ReflectUtil.invoke(example, "setRowsPerPage", ptypes, new Object[]{Integer.valueOf(page.getRowsPerPage())});
        }

        Method method = mapper.getClass().getMethod("selectOneByExample", new Class[]{example.getClass()});
        Object result = method.invoke(mapper, new Object[]{example});
        if(result != null) {
            page.setData((List)result);
        }

        method = mapper.getClass().getMethod("countByExample", new Class[]{example.getClass()});
        result = method.invoke(mapper, new Object[]{example});
        if(result != null) {
            page.setRowCount(Integer.parseInt(result.toString()));
        }

    }

    public List selectFullByExample(Object example) throws SecurityException, NoSuchMethodException, IllegalArgumentException, IllegalAccessException, InvocationTargetException {
        String pojoName = example.getClass().getSimpleName().replaceAll("Example$", "");
        Object mapper = this.getMapper(pojoName);
        Method method = this.getMethodContainsSuperClass(mapper.getClass(), "selectFullByExample", new Class[]{example.getClass()});
        Object result = method.invoke(mapper, new Object[]{example});
        return result != null?(List)result:null;
    }
}
